package org.smile.strate.api;

import org.smile.Smile;
import org.smile.commons.Strings;
import org.smile.http.HttpFileCache;
import org.smile.io.FileNameUtils;
import org.smile.strate.ActionConstants;
import org.smile.strate.action.SingtonActionSupport;
import org.smile.strate.ann.ActionPackage;
import org.smile.strate.ann.GetMapping;
import org.smile.strate.dispatch.ActionURLInfo;
import org.smile.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@ActionPackage(namespace = ApiServiceConstants.apiNamespace, extend = Strings.BLANK)
public class ApiServiceAction extends SingtonActionSupport {
    /***
     * 文件缓存容器
     */
    private static final HttpFileCache cacheContext = new HttpFileCache();

    protected Map<String, ApiService> serviceAjaxJsMap = new ConcurrentHashMap<String, ApiService>();

    /**
     * 写资源文件方法
     *
     * @param fileName
     * @throws IOException
     */
    @GetMapping(url = "resource/{fileName}")
    public void resource(String fileName) throws IOException {
        HttpServletRequest request = request();
        String pathName = ApiServiceConstants.resourcePath + fileName;
        if (cacheContext.isUseCache(request, pathName)) {
            HttpFileCache.setHeaderNoModified(response());
        } else {
            byte[] file = cacheContext.findFileByPathName(pathName);
            String extName = FileNameUtils.getExtension(fileName);
            HttpFileCache.setHeaderCache(response(), extName, ApiServiceConstants.resourceCacheTimes);
            response().getOutputStream().write(file);
        }

    }

    /**
     * api代码
     *
     * @param serviceName
     */
    @GetMapping(url = "apiCode/{serviceName}")
    public void apiCode(String serviceName,ActionURLInfo urlInfo) throws IOException {
        HttpServletRequest request = request();
        HttpServletResponse response = response();
        String outStr = Strings.BLANK;
        String charset = request.getCharacterEncoding();
        if (charset == null) {
            charset = Smile.ENCODE;
        }
        outStr = generateServiceCode(request, response,serviceName,urlInfo);
        response.setContentType("text/plain;" + charset);
        response.setStatus(HttpServletResponse.SC_OK);
        write(response, outStr, charset);
    }

    /**
     * 写入返回内容到response中
     *
     * @param response
     * @param content
     * @param charset
     * @throws IOException
     */
    protected void write(HttpServletResponse response, String content, String charset) throws IOException {
        if (content != null) {
            OutputStream out = response.getOutputStream();
            try {
                byte[] bout = content.getBytes(charset);
                response.setIntHeader("Content-Length", bout.length);
                out.write(bout);
                out.flush();
            } finally {
                out.close();
            }
        }
    }

    protected String getBasePath(HttpServletRequest request) {
        String path = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/";
        return path;
    }

    /**
     * 创建js文件
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    public String generateServiceCode(HttpServletRequest request, HttpServletResponse response, String serviceName,ActionURLInfo urlInfo) throws IOException {
        String uri= request.getRequestURI();
    	String actionPath = StringUtils.substringAfter(uri, request.getContextPath());
    	actionPath=StringUtils.substringBeforeLast(actionPath, "/");
    	if(!urlInfo.isSuffix()) {//不是后缀方式时云去除前缀
    		actionPath=StringUtils.substringAfter(actionPath, urlInfo.getActionFlag()+'/');
    	}
        String path = getBasePath(request);
        if (!actionPath.endsWith("/")) {//处理是否以/结束
            actionPath += "/";
        }
        if (actionPath.startsWith("/")) {
            actionPath = actionPath.substring(1);
        }
        String actionSuffix=Strings.BLANK;
        if(ApiServiceConstants.apiEnableSuffix) {
        	actionSuffix=Strings.DOT+ActionConstants.extension;
        }
        String ext = FileNameUtils.getExtension(request.getRequestURI());
        try {
            ApiService ajaxJs = serviceAjaxJsMap.get(serviceName);
            if (ajaxJs == null) {
                ajaxJs = new ApiService(request.getServletContext(), serviceName);
                serviceAjaxJsMap.put(path, ajaxJs);
            }
            ApiService.ApiCode code = ajaxJs.getApiCode(path,actionPath,actionSuffix );
            if (HttpFileCache.isUseCache(request, code.times)) {
                //使用缓存不返回信息
                HttpFileCache.setHeaderNoModified(response);
                return null;
            } else {
                //设置业务js缓存
                HttpFileCache.setHeaderCache(response, ext, 120000);
                return code.content;
            }
        } catch (Exception e) {
            logger.error(e);
            StringBuffer strbuf = new StringBuffer();
            strbuf.append("var str=\"generate service error: ").append(serviceName).append("\\n\";");
            strbuf.append("str = str + \"").append(e.getMessage()).append("\";");
            strbuf.append("alert(str);");
            return strbuf.toString();
        }
    }
}
